//
//  ARAudioRecordManager.m
//  AwesomeRecorder
//
//  Created by Xing on 2019/11/29.
//  Copyright © 2019 Xing. All rights reserved.
//

#import "ARAudioRecordManager.h"
#import <AVFoundation/AVFoundation.h>
#import "CRHeader.h"

@interface ARAudioRecordManager()<AVAudioRecorderDelegate>

proStrong AVAudioRecorder *recorder;

@end

@implementation ARAudioRecordManager

+ (instancetype)sharedInstance {
    
    static dispatch_once_t once;
    static id __singleton__;
    dispatch_once( &once, ^{ __singleton__ = [[self alloc] init]; });
    return __singleton__;
}

- (instancetype)init {
    
    self = [super init];
    if (self) {
        [self defaultConfig];
    }
    return self;
}

- (void)defaultConfig {
    
    //录音设置
    NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
    //设置录音格式 AVFormatIDKey==kAudioFormatLinearPCM
    [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
    //设置录音采样率(Hz) 如：AVSampleRateKey==8000/44100/96000（影响音频的质量）, 采样率必须要设为11025才能使转化成mp3格式后不会失真
    [recordSetting setValue:[NSNumber numberWithFloat:16000] forKey:AVSampleRateKey];
    //录音通道数 1 或 2 ，要转换成mp3格式必须为双通道
    [recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
    //线性采样位数 8、16、24、32
    [recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
    //录音的质量
    [recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];
    // 设置录制音频采用高位优先的记录格式
    [recordSetting setValue:[NSNumber numberWithBool:YES] forKey:AVLinearPCMIsBigEndianKey];
    // 设置采样信号采用浮点数
    [recordSetting setValue:[NSNumber numberWithBool:YES] forKey:AVLinearPCMIsFloatKey];
    
    //存储录音文件
    NSURL * recordUrl = [NSURL fileURLWithPath:kRecordAudioCacheFilePath];
    //初始化录音对象
    NSError * error;
    _recorder = [[AVAudioRecorder alloc] initWithURL:recordUrl settings:recordSetting error:&error];
    if (error) {
        NSLog(@"%@",error.description);
        return;
    }
    _recorder.delegate = self;
    //开启音量检测
    _recorder.meteringEnabled = YES;
}

- (void)start {
    
    if (self.isRecording) {
        return;
    }
    
    if ([self.recorder isRecording]) {
        [self.recorder stop];
    }
    if ([self.recorder currentTime]>0) {
        [self.recorder deleteRecording];
    }
    
    AVAudioSession * audioSession = [AVAudioSession sharedInstance];//得到音频会话单例对象
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];//设置类别,表示该应用同时支持播放和录音
    [audioSession setActive:YES error:nil];//激活当前应用的音频会话,此时会阻断后台音乐的播放.
    
    //准备录音
    [self.recorder prepareToRecord];
    
    //开始录音
    [self.recorder record];
    self.isRecording = YES;
}

- (void)pause {
    
    [self.recorder pause];
    self.isRecording = NO;
}

- (void)record {
    
    [self.recorder record];
    self.isRecording = YES;
}

- (void)stop {
    
    [self.recorder stop];
    self.isRecording = NO;
}

- (NSTimeInterval)currentTime {
    
    return [self.recorder currentTime];
}

/**
 合并录音
 
 @param paths 路径
 @param outputURL 输出路径
 @param finish 回调
 */
- (void)mergeAudios:(NSArray <NSURL *>*)paths destnation:(NSURL *)outputURL finish:(void(^)(bool success,NSTimeInterval time))finish {
    
    if (paths.count == 0 || outputURL == nil) {
        return;
    }
    
    AVMutableComposition *composition = [AVMutableComposition composition];
    // 设置音频合并音轨
    AVMutableCompositionTrack *compositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    // 开始时间
    CMTime beginTime = kCMTimeZero;
    NSError *error = nil;
    for (NSURL *url in paths) {
        // 音频文件资源
        AVURLAsset *asset = [AVURLAsset assetWithURL:url];
        // 需要合并的音频文件的区间
        CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
        // ofTrack 音频文件内容
        AVAssetTrack *track = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;
        //
        [compositionTrack insertTimeRange:timeRange ofTrack:track atTime:beginTime error:&error];
        if (error) {
            NSLog(@"error:%@",error);
        }
        
        beginTime = CMTimeAdd(beginTime, asset.duration);
    }
    
    [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
    
    // 导出合并的音频
    // presetName 与 outputFileType 要对应
    AVAssetExportSession *export = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetAppleM4A];
    export.outputURL = outputURL;
    export.outputFileType = AVFileTypeAppleM4A;
    export.shouldOptimizeForNetworkUse = YES;
    [export exportAsynchronouslyWithCompletionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (finish) {
                if(export.status == AVAssetExportSessionStatusCompleted) {
                    AVURLAsset *asset = [AVURLAsset assetWithURL:outputURL];
                    int64_t seconds = asset.duration.value / asset.duration.timescale;
                    
                    finish(YES, seconds);
                }else if(export.status == AVAssetExportSessionStatusFailed){
                    NSLog(@"export failed:%@",error);
                    finish(NO, 0);
                }
            }
        });
    }];
}

#pragma mark -
#pragma mark AVAudioRecorderDelegate

//录音结束后代理
-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag {
    
    [[AVAudioSession sharedInstance] setActive:NO error:nil];//一定要在录音停止以后再关闭音频会话管理（否则会报错），此时会延续后台音乐播放
    
    if (!flag) return;
}

@end
